package com.etone.smartAudit.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.etone.smartAudit.domain.Admin;
import com.etone.smartAudit.domain.Item;
import com.etone.smartAudit.domain.ProjectFile;
import com.etone.smartAudit.domain.ProjectFileCollect;
import com.etone.smartAudit.error.CustomParameterizedException;
import com.etone.smartAudit.mapper.ProjectFileCollectMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.etone.smartAudit.vo.PagerVO;
import com.etone.smartAudit.vo.projectFile.ProjectFileDirVO;
import com.etone.smartAudit.vo.projectFile.ProjectFileVO;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

import static com.etone.smartAudit.service.ProjectFileService.IS_FILE_TYPE_YES;

/**
 * <p>
 * 文件收藏表 文件收藏表 服务实现类
 * </p>
 *
 * @author jiayen
 * @since 2021-05-08
 */
@Service
public class ProjectFileCollectService extends ServiceImpl<ProjectFileCollectMapper, ProjectFileCollect> {


    @Autowired
    private ProjectFileService projectFileService;


    @Autowired
    private ItemService itemService;


    @Autowired
    private ProjectFileCollectMapper collectMapper;

    @Autowired
    private OfficeFileService officeFileService;

    /***
     * 收藏指定文件
     * @param admin
     * @param fId
     */
    public void collectFile(Admin admin, Integer fId) {
        ProjectFile file = projectFileService.getById(fId);
        if (file == null) {
            throw new CustomParameterizedException("当前文件不存在!");
        }

        //判断文件是否被收藏
        LambdaQueryWrapper<ProjectFileCollect> query = new LambdaQueryWrapper<>();
        query.eq(ProjectFileCollect::getFileId, fId)
                .eq(ProjectFileCollect::getCreatedBy, admin.getId());
        List<ProjectFileCollect> list = this.list(query);
        if (CollectionUtil.isNotEmpty(list)) {
            throw new CustomParameterizedException("当前文件已被收藏，请不要重复操作!");
        }
        //执行收藏
        ProjectFileCollect collect = new ProjectFileCollect();
        collect.setFileId(fId);
        collect.setCreatedBy(admin.getId());
        collect.setCreatedName(admin.getNickName());
        collect.setUpdatedTime(new Date());
        collect.setType(file.getType());
        collect.setCreatedTime(new Date());
        this.save(collect);
    }

    /***
     * 取消文件收藏
     * @param admin
     * @param fId
     */
    public void cancleCollect(Admin admin, Integer fId) {
        ProjectFile file = projectFileService.getById(fId);
        if (file == null) {
            throw new CustomParameterizedException("当前文件不存在");
        }

        //判断文件是否被收藏
        LambdaQueryWrapper<ProjectFileCollect> query = new LambdaQueryWrapper<>();
        query.eq(ProjectFileCollect::getFileId, fId)
                .eq(ProjectFileCollect::getCreatedBy, admin.getId());
        List<ProjectFileCollect> list = this.list(query);
        if (CollectionUtil.isEmpty(list)) {
            throw new CustomParameterizedException("当前文件未收藏!");
        }
        //执行取消操作
        this.remove(query);
    }

    /***
     * 收藏文件列表
     * @param admin
     * @return
     */
    public ProjectFileDirVO collectList(Admin admin) {
        //获取收藏的列表  区分文件于文件夹

        //获取项目列表
        List<Item> itemList = itemService.getItemsByAdminId(admin.getId());
        if (CollectionUtil.isEmpty(itemList)) {
            return new ProjectFileDirVO();
        }

        Map<Integer, Item> itemMap = new HashMap<>();
        //获取属于该项目的文件夹
        List<Integer> projectIds = itemList.stream().map(item -> {
                    itemMap.put(item.getId(), item);
                    return item.getId();
                }
        ).collect(Collectors.toList());
        List<ProjectFileDirVO> projectDirs = projectFileService.getProjectFileDirList(projectIds);

        Map<Integer, ProjectFileDirVO> dirMap = new HashMap<>();
//        if (CollectionUtil.isEmpty(projectDirs)) {
//            return new ProjectFileDirVO();
//        }
        projectDirs.stream().forEach(dir -> {
            dirMap.put(dir.getId(), dir);
        });

        //获取收藏的文件夹
        List<ProjectFileCollect> list = collectMapper.getCollectFiles(admin.getId());

        if (CollectionUtil.isEmpty(list)) {
            return new ProjectFileDirVO();
        }

        //过滤文件树 显示收藏相关的文件树
        Set<Integer> fileIds = new HashSet<>();
        List<Integer> realProjectIds = new ArrayList<>();

        list.stream().forEach(collect -> {
            Integer type = collect.getFileType();
            if (type == null) {
                type = collect.getType();
            }
            if (type != null) {
                realProjectIds.add(collect.getProjectId());
                //是文件夹，则对于子文件拥有所有权限
                if (type == ProjectFileService.IS_FILE_TYPE_NO) {
                    //遍历顶部
                    getCurTopList(dirMap.get(collect.getFileId()), dirMap, fileIds);
                } else {
                    //如果是文件则获取他的上级文件夹id
                    //遍历顶部
                    getCurTopList(dirMap.get(collect.getFilePid()), dirMap, fileIds);
                }
            }
        });

        //记录所属的项目id
        List<Integer> itemIds = new ArrayList<>();
        List<Item> realItem = new ArrayList<>();

        //获取实际的项目文件目录
        List<ProjectFileDirVO> expandList = new ArrayList<>();
        realProjectIds.stream().forEach(itemId -> {
            if (!itemIds.contains(itemId)) {
                itemIds.add(itemId);
                Item r_item = itemMap.get(itemId);
                if(r_item!=null) {
                    realItem.add(r_item);
                }
            }
        });

        fileIds.stream().forEach(id -> {
            ProjectFileDirVO vo = dirMap.get(id);
            if (vo != null) {
                expandList.add(vo);
            }
        });
        ProjectFileDirVO treeList = projectFileService.handProjectFiles(realItem, expandList);
        return treeList;
    }


    /***
     * 获取顶部数据集合
     * @param curVo
     * @param dirMap
     * @param fileIds
     * @return
     */
    public Set<Integer> getCurTopList(ProjectFileDirVO curVo, Map<Integer, ProjectFileDirVO> dirMap, Set<Integer> fileIds) {
        if (curVo == null) {
            return fileIds;
        }
        Integer id = curVo.getId();
        fileIds.add(id);
        ProjectFileDirVO parentFile = dirMap.get(curVo.getPid());
        if (parentFile != null) {
            getCurTopList(parentFile, dirMap, fileIds);
        }
        return fileIds;
    }

    /***
     * 获取指定的文件夹下得收藏文件
     * @param admin
     * @param fId
     * @param page
     * @param pageSize
     * @param projectId
     * @param fileName
     * @return
     */
    public PagerVO<ProjectFileVO> collectFiles(Admin admin, Integer fId, int page, int pageSize, int projectId, String fileName) {
        //判断是否有收藏该文件夹，或者该文件夹的上级文件夹 包含则可以获取其下所有子集文件
        if (hasFileDirPermission(admin, fId, projectId)) {
            //获取项目
            //则获取文件夹下的所有文件
            return projectFileService.getFilesByPId(admin, fId, page, pageSize, projectId, fileName,-1);
        } else {
            //获取其文件夹下收藏的文件
            Page<ProjectFileVO> pagerVO = PageHelper.startPage(page, pageSize).doSelectPage(() -> collectMapper.getFilesByPId(fId, projectId, fileName));
            pagerVO.getResult().stream().forEach(vo -> {
                if (IS_FILE_TYPE_YES == vo.getType()) {
                    //判断文件是否在编辑中
                    vo.setStatus(officeFileService.userIsEdit(admin, vo.getId()));
                }
                if(!StringUtils.isEmpty(vo.getSize())) {
                    vo.setSize(FileUtil.readableFileSize(Long.valueOf(vo.getSize())));
                }
                vo.setIsCollect(true);
            });
            return PagerVO.of(pagerVO);
        }
    }


    /***
     * 判断该文件夹是否是收藏的权限文件夹
     * @param admin
     * @param fId
     * @return
     */
    private boolean hasFileDirPermission(Admin admin, Integer fId, Integer projectId) {
        //判断是否有收藏该文件夹，或者该文件夹的上级文件夹 包含则可以获取其下所有子集文件
        //判断文件是否被收藏
        LambdaQueryWrapper<ProjectFileCollect> query = new LambdaQueryWrapper<>();
        query.eq(ProjectFileCollect::getFileId, fId)
                .eq(ProjectFileCollect::getCreatedBy, admin.getId());
        List<ProjectFileCollect> list = this.list(query);
        if (CollectionUtil.isEmpty(list)) {
            List<Integer> projectIds = new ArrayList<Integer>() {{
                add(projectId);
            }};
//            List<ProjectFileDirVO> projectDirs = projectFileService.getProjectFileDirList(projectIds);
            List<ProjectFileDirVO> projectDirs = collectMapper.getProjectFileDirList(projectIds, admin.getId());
            if (CollectionUtil.isEmpty(projectDirs)) {
                return false;
            }
            Map<Integer, ProjectFileDirVO> dirMap = projectDirs.stream().collect(Collectors.toMap(ProjectFileDirVO::getId, vo -> vo));
            Set<Integer> parentIds = new HashSet<>();
            getCurTopList(dirMap.get(fId), dirMap, parentIds);
            if (parentIds.contains(fId)) {
                //说明有收藏其父级，可以拥有所有子文件的权限
                return true;
            }
        } else {
            return true;
        }
        return false;
    }

}
